const fs = require("fs");
const path = require("path");
const http = require("http");
const https = require("https");
const url = require("url");
const buffer = require("buffer");
const util = require("util");


class Toolbox {
  /**
   * @returns {Promise<{ok:Boolean,msg:string,stats:import("fs").Stats}>}
   * @param {String} full_path 
   */
  static getStats(full_path) {
    return new Promise(resolve => {
      fs.stat(full_path, (err, stats) => {
        if (err) {
          return resolve({
            ok: false,
            msg: err.message
          })
        }
        resolve({
          ok: true,
          msg: "ok",
          stats: stats
        })
      })
    })
  }

  /**
   * @returns {Promise<Array<{relative_path:String,full_path:String,stats:import("fs").Stats}>>}
   * @param {String} full_Path_to_dir must be a dir
   */
  static safeListDir(full_Path_to_dir) {
    return new Promise(resolve => {
      fs.readdir(full_Path_to_dir, async (err, files) => {
        if (err) {
          console.error(err.message);
          return resolve([])
        }
        let o_getStats = await Promise.all(files.map(file => this.getStats(path.join(full_Path_to_dir, file))));
        let results = o_getStats.map((o, i) => {
          return {
            relative_path: files[i],
            o_get_stats: o,
            full_path: path.join(full_Path_to_dir, files[i])
          }
        });
        results = results.filter(r => r.o_get_stats.ok);
        let stats_results = results.map(e => {
          return {
            relative_path: e.relative_path,
            full_path: e.full_path,
            stats: e.o_get_stats.stats
          }
        })
        resolve(stats_results);
      })
    })
  }

  /**
   *
   * @return {Promise<{ok:Boolean,msg:String,json_data:Object}>}
   * @static
   * @param {import("fs").ReadStream} stream
   * @param {String} target_url
   * @param {Number} timeout
   * @param {import("http").OutgoingHttpHeaders} request_headers
   * @memberof Toolbox
   */
  static WrapHttpPostStream(stream, target_url, request_headers, timeout = 60 * 1000) {
    let parsed = url.parse(target_url);
    let _http = parsed.protocol.includes("https") ? https : http;
    return new Promise(resolve => {
      let response_flag = false;
      let request = _http.request({
        host: parsed.host,
        path: parsed.path,
        protocol: parsed.protocol,
        headers: request_headers,
        timeout: 60 * 1000 * 3//好像没有起到作用????
      }, (res) => {
        response_flag = true;


        let buf = new buffer.Buffer("");
        res.on("data", chunk => buf += chunk);
        res.on("end", $ => {
          if (!res.headers['content-type'].includes("application/json")) {
            return resolve({
              ok: false,
              msg: `response type is not application/json:${buf.toString()}`
            })
          }
          let json_str = buf.toString();
          if (res.statusCode != 200) {
            return resolve({
              ok: false,
              msg: `http status is ${res.statusCode},content is ${json_str}`
            })
          }
          try {
            let obj = JSON.parse(json_str);
            resolve({
              ok: true,
              msg: "ok",
              json_data: obj
            })
          } catch (e) {
            resolve({
              ok: false,
              msg: `error when JSON.parse :${e.message ? e.message : util.inspect(e)}`
            })
          }
        });
        res.on("error", res_err => resolve({
          ok: false,
          msg: `res.on("error"):${res_err.message}`
        }))
      });
      request.on("error", (request_err) => resolve({
        ok: false,
        msg: `request.on("error"):${request_err.message}`
      }))
      stream.pipe(request);
      stream.on("close", () => {
        setTimeout(() => {
          if (!response_flag) {
            resolve({
              ok: false,
              msg: `手工TIMEOUT:经过${timeout / 1000}s 后没有response`
            })
          }
        }, timeout)
      })
    })




  }
}


module.exports = Toolbox